package start.spring.basic.util.common;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.crypto.digests.SM3Digest;


/**
 * ****************************************************************************
 * 加密工具类，目前包括base64编解码，MD2\MD5\SHA\SHA-256\SHA-384\SHA-512\AES\RSA加密
 *
 * @author(作者)：xuyongyun	
 * @author(复审人)：	xu 2016-4-12
 * @version(版本)1.0
 * @since 1.0
 ******************************************************************************
 */

public class EncryptUtil{
	
	public static final String MD2 = "MD2";
	public static final String MD5 = "MD5";
	public static final String SHA = "SHA";
	public static final String SHA1 = "SHA1";
    public static final String SHA_256 = "SHA-256";
    public static final String SHA_384 = "SHA-384";
    public static final String SHA_512 = "SHA-512";
    
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
    
    /**
     * 获取公钥的key
     */
    public static final String PUBLIC_KEY = "RSAPublicKey";
    
    /**
     * 获取私钥的key
     */
    public static final String PRIVATE_KEY = "RSAPrivateKey";
    
    /**
     * Base64加密
     * @param str
     * @return
     * @throws UnsupportedEncodingException 
     */
    public static String getBase64(String str) throws UnsupportedEncodingException{  
        byte[] b=null;  
        String s=null;
        b = str.getBytes("utf-8"); 
        if(b!=null){  
            s = Base64.encodeBase64String(b);  
        }  
        return StringUtil.trimEnter(s);  
    }
    
    /**
     * Base64解密
     * @param str
     * @return
     * @throws IOException 
     */  
    public static String getFromBase64(String s) throws IOException {    
        byte[] b = null;    
        String result = null;    
        if (s != null) {
            b = Base64.decodeBase64(s);
            result = new String(b, "utf-8");
        }
        return result;    
    }
    
    /** 
     * BASE64解密 
     *  
     * @param key 
     * @return 
     * @throws Exception 
     */  
	public static byte[] decryptBASE64(String key) throws Exception {  
        return Base64.decodeBase64(key);  
    }
	
	public static String byteToString(byte[] byteArray) throws UnsupportedEncodingException{
		return new String(byteArray);  
	}
	
	 /** 
     * BASE64加密 
     *  
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static String encryptBASE64(byte[] key) throws Exception {
        return StringUtil.trimEnter(Base64.encodeBase64String(key));  
    } 
    
    /**
     * 摘要算法
     * 
     * @param sourceStr 需要获取摘要字符串
     * @param algorithmsName 算法名称(如:MD2,MD5,SHA-1,SHA-256)
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String encrypt(String sourceStr,String algorithmsName) throws NoSuchAlgorithmException{
        String encryptString = "";
        MessageDigest md;
        
        md = MessageDigest.getInstance(algorithmsName);
        // 使用指定byte[]更新摘要
        md.update(sourceStr.getBytes());
        // 完成计算，返回结果数组
        byte[] b = md.digest();
        encryptString = StringUtil.byteArrayToHex(b);
        encryptString = StringUtil.trimEnter(encryptString);
        
        return encryptString;
    }
    
    /**
     * SM3字符串摘要算法
     * 
     * @param sourceStr 需要获取摘要字符串
     * @param 
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String encryptSm3(String sourceStr) throws NoSuchAlgorithmException{
        String encryptString = "";
        SM3Digest digest = new SM3Digest();
        byte[] input = sourceStr.getBytes();
        digest.update(input, 0, input.length);
        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        encryptString = StringUtil.byteArrayToHex(result);
        encryptString = StringUtil.trimEnter(encryptString);
        
        return encryptString;
    }
    
    /**
     * SM3文件摘要算法
     * 
     * @param input 需要获取摘要文件二进制流
     * @param 
     * @return
     * @throws NoSuchAlgorithmException 
     */
    public static String encryptSm3(byte[] input) throws NoSuchAlgorithmException{
        String encryptString = "";
        SM3Digest digest = new SM3Digest();
        digest.update(input, 0, input.length);
        byte[] result = new byte[digest.getDigestSize()];
        digest.doFinal(result, 0);
        encryptString = StringUtil.byteArrayToHex(result);
        encryptString = StringUtil.trimEnter(encryptString);
        
        return encryptString;
    }
    
    /*
     * ***********************************************************
     * ***********************************************************
     * 以下为AES加密解密方法
     * 
     * ***********************************************************
     * ***********************************************************
     */
    /**
	 * 转换密钥
	 * @param key
	 * @return
	 * @throws Exception
	 */
	private static Key toKey(String key) throws Exception{
		SecretKey secretKey = new SecretKeySpec(key.getBytes(),"AES");
		return secretKey;
	}
	
	/**
	 * 对数据进行解密
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String decryptAes(String data,String key) throws Exception{
		Key k = toKey(key);
		Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
		IvParameterSpec iv = new IvParameterSpec(key.getBytes());
		cipher.init(Cipher.DECRYPT_MODE, k,iv);
		return new String(cipher.doFinal(decryptBASE64(data)));
	}
	
	/**
	 * 对数据进行加密
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static String encryptAes(String data,String key) throws Exception{
		Key k = toKey(key);
		IvParameterSpec iv = new IvParameterSpec(key.getBytes());
		Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
		cipher.init(Cipher.ENCRYPT_MODE, k,iv);
		return encryptBASE64((cipher.doFinal(data.getBytes())));
	}
	
}
